home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / patterns.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-12  |  8.2 KB  |  377 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <glib.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #ifdef HAVE_UNISTD_H
  29. #include <unistd.h>
  30. #endif
  31. #include <fcntl.h>
  32.  
  33. #ifdef G_OS_WIN32
  34. #include <io.h>
  35. #endif
  36.  
  37. #ifndef _O_BINARY
  38. #define _O_BINARY 0
  39. #endif
  40.  
  41. #ifdef HAVE_DIRENT_H
  42. #include <dirent.h>
  43. #endif
  44.  
  45. #include <glib.h>
  46.  
  47. #include "datafiles.h"
  48. #include "patterns.h"
  49. #include "pattern_header.h"
  50. #include "gimpcontext.h"
  51. #include "gimprc.h"
  52.  
  53. #include "libgimp/gimpintl.h"
  54.  
  55.  
  56. /*  global variables  */
  57. GPattern *active_pattern = NULL;
  58. GSList   *pattern_list   = NULL;
  59. gint      num_patterns   = 0;
  60.  
  61.  
  62. /*  static variables  */
  63. static GPattern *standard_pattern = NULL;
  64.  
  65.  
  66. /*  local function prototypes  */
  67. static GPattern *  pattern_load_real      (gint           fd,
  68.                        gchar         *filename,
  69.                        gboolean       quiet);
  70. static void        load_pattern           (gchar         *filename);
  71. static void        pattern_free_func      (gpointer       data, 
  72.                        gpointer       dummy);
  73. static gint        pattern_compare_func   (gconstpointer  second, 
  74.                        gconstpointer  first);
  75.  
  76. /*  public functions  */
  77.  
  78. void
  79. patterns_init (gboolean no_data)
  80. {
  81.   GSList *list;
  82.  
  83.   if (pattern_list)
  84.     patterns_free ();
  85.  
  86.   if (pattern_path != NULL && !no_data)
  87.     datafiles_read_directories (pattern_path, load_pattern, 0);
  88.  
  89.   /*  assign indexes to the loaded patterns  */
  90.   for (list = pattern_list; list; list = g_slist_next (list))
  91.     {
  92.       /*  Set the pattern index  */
  93.       ((GPattern *) list->data)->index = num_patterns++;
  94.     }
  95.  
  96.   gimp_context_refresh_patterns ();
  97. }
  98.  
  99. void
  100. patterns_free (void)
  101. {
  102.   if (pattern_list)
  103.     {
  104.       g_slist_foreach (pattern_list, pattern_free_func, NULL);
  105.       g_slist_free (pattern_list);
  106.     }
  107.  
  108.   num_patterns = 0;
  109.   pattern_list = NULL;
  110. }
  111.  
  112. GPattern *
  113. patterns_get_standard_pattern (void)
  114. {
  115.   if (! standard_pattern)
  116.     {
  117.       guchar *data;
  118.       gint row, col;
  119.  
  120.       standard_pattern = g_new (GPattern, 1);
  121.  
  122.       standard_pattern->filename = NULL;
  123.       standard_pattern->name     = g_strdup ("Standard");
  124.       standard_pattern->index    = -1;  /*  not part of the pattern list  */
  125.       standard_pattern->mask     = temp_buf_new (32, 32, 3, 0, 0, NULL);
  126.  
  127.       data = temp_buf_data (standard_pattern->mask);
  128.  
  129.       for (row = 0; row < standard_pattern->mask->height; row++)
  130.     for (col = 0; col < standard_pattern->mask->width; col++)
  131.       {
  132.         memset (data, (col % 2) && (row % 2) ? 255 : 0, 3);
  133.         data += 3;
  134.       }
  135.     }
  136.  
  137.   return standard_pattern;
  138. }
  139.  
  140. GPattern *
  141. pattern_list_get_pattern_by_index (GSList *list,
  142.                    gint    index)
  143. {
  144.   GPattern *pattern = NULL;
  145.  
  146.   list = g_slist_nth (list, index);
  147.   if (list)
  148.     pattern = (GPattern *) list->data;
  149.  
  150.   return pattern;
  151. }
  152.  
  153. GPattern *
  154. pattern_list_get_pattern (GSList *list,
  155.               gchar  *name)
  156. {
  157.   GPattern *pattern;
  158.  
  159.   if (name == NULL)
  160.     return NULL;
  161.  
  162.   for (; list; list = g_slist_next (list))
  163.     {
  164.       pattern = (GPattern *) list->data;
  165.       
  166.       if (!strcmp (pattern->name, name))
  167.     return pattern;
  168.     }
  169.  
  170.   return NULL;
  171. }
  172.  
  173. GPattern *
  174. pattern_load (gint      fd,
  175.           gchar    *filename)
  176. {
  177.   return pattern_load_real (fd, filename, TRUE);
  178. }
  179.  
  180. static GPattern *
  181. pattern_load_real (gint      fd,
  182.                gchar    *filename,
  183.                gboolean  quiet)
  184. {
  185.   GPattern      *pattern;
  186.   PatternHeader  header;
  187.   gint    bn_size;
  188.   gchar  *name;
  189.  
  190.   g_return_val_if_fail (filename != NULL, NULL);
  191.   g_return_val_if_fail (fd != -1, NULL);
  192.  
  193.   /*  Read in the header size  */
  194.   if (read (fd, &header, sizeof (header)) != sizeof (header)) 
  195.     return NULL;
  196.  
  197.   /*  rearrange the bytes in each unsigned int  */
  198.   header.header_size  = g_ntohl (header.header_size);
  199.   header.version      = g_ntohl (header.version);
  200.   header.width        = g_ntohl (header.width);
  201.   header.height       = g_ntohl (header.height);
  202.   header.bytes        = g_ntohl (header.bytes);
  203.   header.magic_number = g_ntohl (header.magic_number);
  204.  
  205.  /*  Check for correct file format */
  206.   if (header.magic_number != GPATTERN_MAGIC || header.version != 1 || 
  207.       header.header_size <= sizeof (header)) 
  208.     {
  209.       if (!quiet)
  210.     g_message (_("Unknown pattern format version #%d in \"%s\"."),
  211.            header.version, filename);
  212.       return NULL;
  213.     }
  214.   
  215.   /*  Check for supported bit depths  */
  216.   if (header.bytes != 1 && header.bytes != 3)
  217.     {
  218.       g_message ("Unsupported pattern depth: %d\n in file \"%s\"\nGIMP Patterns must be GRAY or RGB\n",
  219.          header.bytes, filename);
  220.       return NULL;
  221.     }
  222.  
  223.    /*  Read in the brush name  */
  224.   if ((bn_size = (header.header_size - sizeof (header))))
  225.     {
  226.       name = g_new (gchar, bn_size);
  227.       if ((read (fd, name, bn_size)) < bn_size)
  228.     {
  229.       g_message (_("Error in GIMP pattern file \"%s\"."), filename);
  230.       g_free (name);
  231.       return NULL;
  232.     }
  233.     }
  234.   else
  235.     {
  236.       name = g_strdup (_("Unnamed"));
  237.     }
  238.  
  239.   pattern = g_new0 (GPattern, 1);
  240.   pattern->mask = temp_buf_new (header.width, header.height, header.bytes,
  241.                 0, 0, NULL);
  242.   if (read (fd, temp_buf_data (pattern->mask), 
  243.         header.width * header.height * header.bytes) < header.width * header.height * header.bytes)
  244.       {
  245.     g_message (_("GIMP pattern file appears to be truncated: \"%s\"."),
  246.            filename);
  247.     pattern_free (pattern);
  248.     return NULL;
  249.       }
  250.  
  251.   pattern->name = name;
  252.  
  253.   return pattern;
  254. }
  255.  
  256. void
  257. pattern_free (GPattern *pattern)
  258. {
  259.   if (pattern->mask)
  260.     temp_buf_free (pattern->mask);
  261.   if (pattern->filename)
  262.     g_free (pattern->filename);
  263.   if (pattern->name)
  264.     g_free (pattern->name);
  265.  
  266.   g_free (pattern);
  267. }
  268.  
  269. /*  private functions  */
  270.  
  271. static void
  272. pattern_free_func (gpointer data,
  273.            gpointer dummy)
  274. {
  275.   pattern_free ((GPattern *) data);
  276. }
  277.  
  278. static gint
  279. pattern_compare_func (gconstpointer first,
  280.               gconstpointer second)
  281. {
  282.   return strcmp (((const GPattern *) first)->name, 
  283.          ((const GPattern *) second)->name);
  284. }
  285.  
  286. static void
  287. load_pattern (gchar *filename)
  288. {
  289.   GPattern *pattern;
  290.   gint      fd;
  291.   GSList   *list;
  292.   GSList   *list2;
  293.   gint      unique_ext = 0;
  294.   gchar    *ext;
  295.   gchar    *new_name = NULL;
  296.  
  297.   g_return_if_fail (filename != NULL);
  298.  
  299.   fd = open (filename, O_RDONLY | _O_BINARY);
  300.   if (fd == -1) 
  301.     return;
  302.  
  303.   pattern = pattern_load_real (fd, filename, FALSE);
  304.  
  305.   close (fd);
  306.  
  307.   if (!pattern)
  308.     return;
  309.  
  310.   pattern->filename = g_strdup (filename);
  311.  
  312.   /*  Swap the pattern to disk (if we're being stingy with memory) */
  313.   if (stingy_memory_use)
  314.     temp_buf_swap (pattern->mask);
  315.  
  316.   /* uniquefy pattern name */
  317.   for (list = pattern_list; list; list = g_slist_next (list))
  318.     {
  319.       if (! strcmp (((GPattern *) list->data)->name, pattern->name))
  320.     {
  321.       ext = strrchr (pattern->name, '#');
  322.  
  323.       if (ext)
  324.         {
  325.           gchar *ext_str;
  326.  
  327.           unique_ext = atoi (ext + 1);
  328.  
  329.           ext_str = g_strdup_printf ("%d", unique_ext);
  330.  
  331.           /*  check if the extension really is of the form "#<n>"  */
  332.           if (! strcmp (ext_str, ext + 1))
  333.         {
  334.           *ext = '\0';
  335.         }
  336.           else
  337.         {
  338.           unique_ext = 0;
  339.         }
  340.  
  341.           g_free (ext_str);
  342.         }
  343.       else
  344.         {
  345.           unique_ext = 0;
  346.         }
  347.  
  348.       do
  349.         {
  350.           unique_ext++;
  351.  
  352.           g_free (new_name);
  353.  
  354.           new_name = g_strdup_printf ("%s#%d", pattern->name, unique_ext);
  355.  
  356.           for (list2 = pattern_list; list2; list2 = g_slist_next (list2))
  357.         {
  358.           if (! strcmp (((GPattern *) list2->data)->name, new_name))
  359.             {
  360.               break;
  361.             }
  362.         }
  363.         }
  364.       while (list2);
  365.  
  366.       g_free (pattern->name);
  367.  
  368.       pattern->name = new_name;
  369.  
  370.       break;
  371.     }
  372.     }
  373.  
  374.   pattern_list = g_slist_insert_sorted (pattern_list, pattern,
  375.                     pattern_compare_func);
  376. }
  377.